package org.csu.softwaremetrics_demo.metric.lk;

import org.csu.softwaremetrics_demo.entity.common.LKMetricSingleClass;
import org.csu.softwaremetrics_demo.entity.result.Result;
import org.csu.softwaremetrics_demo.metric.Metric;
import org.csu.softwaremetrics_demo.util.ColorLoggerUtils;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.TypeDeclaration;

/**
 * DIT (Depth of Inheritance Tree) 类
 * 用于计算类的继承深度，即从当前类到继承层次结构根的距离。
 *
 * 继承层次越深，类的复杂性和潜在的耦合性越高。
 *
 * DIT值的解释：
 * - 1: 仅继承自Object的类（最小值）
 * - 2-3: 适度继承，通常是好的设计
 * - 4-5: 较深的继承，需要关注
 * - >5: 过深的继承，应考虑重构
 *
 * 注意：
 * 1. 所有类都隐式继承自Object，因此最小DIT值为1
 * 2. 高DIT值表示类设计可能过于复杂
 *
 * @author Jukomu
 * @version 2.0
 */
public class DIT extends ASTVisitor implements Metric<LKMetricSingleClass> {
    private static final ColorLoggerUtils LOGGER = ColorLoggerUtils.getLogger(DIT.class);
    private static final int MAX_INHERITANCE_DEPTH = 20; // 防止潜在的栈溢出
    private static final String OBJECT_CLASS_NAME = "java.lang.Object";

    /**
     * 当前计算的DIT值
     * 初始为1（因为所有类都隐式继承自Object）
     */
    private int dit;

    /**
     * 构造函数
     */
    public DIT() {
        reset();
    }

    /**
     * 重置DIT计算器状态
     */
    public void reset() {
        dit = 1; // Object is the father of everyone!
    }

    /**
     * 访问类型声明节点。
     *
     * @param node 类型声明节点
     * @return 如果成功访问节点，则返回true；否则返回false
     */
    @Override
    public boolean visit(TypeDeclaration node) {
        // 如果节点为空
        if (node == null) {
            LOGGER.warn("Encountered null TypeDeclaration node");
            return false;
        }

        // 获取类型声明的绑定
        ITypeBinding binding = node.resolveBinding();
        // 如果绑定为空
        if (binding == null) {
            LOGGER.warn("Could not resolve binding for type declaration");
            return false;
        }

        // 尝试计算继承深度
        try {
            // 计算继承深度，初始深度为1
            calculateInheritanceDepth(binding, 1);
        } catch (Exception e) {
            // 捕获异常并记录日志
            LOGGER.error("Error calculating DIT: " + e.getMessage(), e);
        }

        // 调用父类的visit方法
        return super.visit(node);
    }


    /**
     * 递归计算类的继承深度
     * 通过递归遍历类的继承层次结构，计算DIT值
     * 包含深度限制以防止栈溢出
     *
     * @param binding 类型绑定对象
     * @param currentDepth 当前递归深度
     */
    private void calculateInheritanceDepth(ITypeBinding binding, int currentDepth) {
        if (binding == null || currentDepth > MAX_INHERITANCE_DEPTH) {
            return;
        }

        ITypeBinding superclass = binding.getSuperclass();
        if (superclass != null) {
            String superclassName = superclass.getQualifiedName();

            // 检查是否为Object类
            if (!OBJECT_CLASS_NAME.equals(superclassName)) {
                dit = Math.max(dit, currentDepth + 1);
                calculateInheritanceDepth(superclass, currentDepth + 1);
            }
        }
    }

    /**
     * 执行DIT计算
     *
     * @param cu          编译单元
     * @param singleMetric 单个度量指标
     * @param result      结果对象
     */
    @Override
    public void execute(CompilationUnit cu, LKMetricSingleClass singleMetric, Result result) {
        if (cu == null || singleMetric == null) {
            LOGGER.error("Cannot execute DIT calculation with null parameters");
            return;
        }

        try {
            reset(); // 确保每次执行都从干净状态开始
            cu.accept(this);
            LOGGER.debug("DIT calculation completed with value: " + dit);
        } catch (Exception e) {
            LOGGER.error("Error during DIT calculation: " + e.getMessage(), e);
            singleMetric.error();
        }
    }

    /**
     * 设置单个指标
     *
     * @param singleMetric 单个指标对象
     */
    @Override
    public void setSingleMetric(LKMetricSingleClass singleMetric) {
        if (singleMetric != null) {
            singleMetric.setDit(dit);
        } else {
            LOGGER.error("Cannot set DIT metric on null object");
        }
    }

    /**
     * 获取当前计算的DIT值
     * 主要用于测试目的
     *
     * @return 当前计算的DIT值
     */
    protected int getDIT() {
        return dit;
    }
}